package com.logic.modular.game.core.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.logic.comment.exection.InfoTips;
import com.comment.exception.ServiceException;
import com.logic.modular.game.battle.info.base.PvpPlayerInfo;
import com.logic.modular.game.battle.info.base.PvpPlayerInfoServiceImpl;
import com.logic.modular.game.core.domain.PvpMatchEnd;
import com.logic.modular.game.player.bag.service.PlayerPropType1ServiceImpl;
import com.logic.modular.game.player.info.service.PlayerStatusServiceImpl;
import com.comment.pojo.domain.logic.domain.PlayerStatus;
import com.logic.modular.game.player.match.PlayerPvpBattleLog;
import com.logic.modular.game.player.match.service.PvpCityServiceImpl;
import com.logic.modular.game.player.match.service.PvpRanksServiceImpl;

import com.comment.pojo.domain.logic.core.PvpMatch;
import com.logic.modular.game.statistical.service.impl.PlayerStatisticalPool2ServiceImpl;
import com.logic.modular.game.statistical.service.impl.PlayerStatisticalPoolServiceImpl;
import com.logic.modular.game.player.task.service.PlayerTaskServiceImpl;
import com.comment.pojo.domain.logic.core.CoreConfig;
import com.logic.modular.gameCore.config.service.impl.CoreConfigServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * pvp对局信息(PvpMatchEnd)表服务实现类
 *
 * @author cxy
 * @since 2024-09-09 11:57:21
 */
@Slf4j
@Service
public class MatchEndServiceImpl
        extends com.logic.modular.game.core.service.base.PvpMatchEndBaseServiceImpl {
    @Resource
    private MatchServiceImpl pvpMatchServiceImpl;
    @Resource
    private PvpPlayerInfoServiceImpl pvpPlayerInfoServiceImpl;
    @Resource
    private MatchServiceImpl pvpMatchService;
    @Resource
    private PlayerStatusServiceImpl playerMatchService;
    @Resource
    private PvpCityServiceImpl pvpCityServiceImpl;
    @Lazy
    @Resource
    private PvpRanksServiceImpl pvpRanksService;
    @Resource
    private MatchExpServiceImpl pvpMatchEndExpService;
    @Resource
    private com.logic.modular.game.core.service.MatchWinPointServiceImpl pvpMatchEndIntegralService;
    @Resource
    private PlayerStatusServiceImpl playerMatchServiceImpl;
    @Lazy
    @Resource
    private PlayerStatisticalPoolServiceImpl playerStatisticalPoolService;
    @Resource
    private PlayerTaskServiceImpl playerTaskServiceImpl;
    @Resource
    private com.logic.modular.game.room.service.PvpRoomServiceImpl pvpRoomServiceImpl;
    @Resource
    private PlayerPropType1ServiceImpl playerPropType1ServiceImpl;
    @Resource
    private PlayerStatusServiceImpl playerStatusServiceImpl;
    @Autowired
    private PlayerStatisticalPool2ServiceImpl playerStatisticalPool2ServiceImpl;

    /**
     * 初始化结算信息
     */
    private void init(Long matchId, Long playerId) {
        PvpPlayerInfo loserInfo = pvpPlayerInfoServiceImpl.get(matchId, playerId);
        PvpMatchEnd build = PvpMatchEnd.builder()
                .matchId(loserInfo.getMatchId())
                .playerId(loserInfo.getPlayerId())
                .eliminatePlayers(loserInfo.getKilledPlayers().size())
                .citiesQuantity(loserInfo.getCurrentCity().size())
                .ranking(loserInfo.getRanking())
                .isRuler(loserInfo.getIsRuler())
                .killedBy(loserInfo.getKilledBy())
                .build();
        save(build);
    }


    /**
     * 退出|结算-经验,积分
     *
     * @return
     */
    // @Transactional
    public PvpMatchEnd exitGame(
            Long playerId,
            Long matchId,
            int endBy
    ) {
        PlayerStatus playerStatus = playerStatusServiceImpl.get(playerId);
        Long currentMatchId = playerStatus.getCurrentMatchId();
        if (currentMatchId < 1) {
            throw new ServiceException("当前不在对局中" + currentMatchId);
        }
        try {
            PvpPlayerInfo loserInfo = pvpPlayerInfoServiceImpl.get(matchId, playerId);
            Long l = loserInfo.obtainSurvivalTime();
            // int quit = Integer.parseInt(CoreConfigServiceImpl.getCache(8L).getValue3());
            // if (l < quit) {
            //     long l1 = quit - l;
            //     throw new InfoTips("玩家游戏时间太短,无法投降!剩余时间:" + l1);
            // }
            PvpMatch byId = pvpMatchService.getById(matchId);
            log.info("玩家:{},退出:{}", playerId, matchId);
            PvpPlayerInfo pvpPlayerInfo = pvpPlayerInfoServiceImpl.get(matchId, playerId);
            pvpPlayerInfo.setIsExit(1);
            pvpPlayerInfoServiceImpl.update(pvpPlayerInfo);
            playerStatisticalPool2ServiceImpl.refreshStatistical(pvpPlayerInfo);
            playerTaskServiceImpl.tryToUpdateTask(playerId);
            //////////////////////////////////////////////////////////////////////////////////////////////////// 结算信息
            init(matchId, playerId);
            Integer type = byId.getType();
            PvpMatchEnd pvpMatchEnd = null;
            if (type == 3) {
                pvpMatchEndIntegralService.obtainIntegralReward(matchId, playerId);
            } else {
                pvpMatchEnd = pvpMatchEndExpService.obtainExpReward(matchId, playerId);
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////  玩家退出对局
            this.clearMatchCopper(playerId);
            PlayerPvpBattleLog.resetPvp(playerId);
            pvpRanksService.resetPvp(playerId);
            playerMatchService.resetPvp(playerId);
            pvpMatchService.resetPvp(matchId, playerId);
            pvpCityServiceImpl.clearAllPlayerCities(loserInfo);
            return pvpMatchEnd;
        } catch (Exception e) {
            log.error("e", e);
            if (e instanceof InfoTips) {
                throw new ServiceException(e.getMessage());
            }
        }
        return null;
    }

    private void clearMatchCopper(Long uid) {
        playerPropType1ServiceImpl.clearCopper(uid, 4L);
        playerPropType1ServiceImpl.clearCopper(uid, 5L);
    }


    /**
     * 尝试武力结束
     */
    @Transactional
    public void tryMilitaryConquestSettlement(Long matchId) {
        pvpPlayerInfoServiceImpl.statisticalRanking(matchId);
        // 检查比赛是否存在
        PvpMatch pvpMatch = pvpMatchServiceImpl.getById(matchId);
        if (pvpMatch == null) {
            throw new IllegalArgumentException("比赛不存在: " + matchId);
        }
        if (pvpMatch.getStatus() == 2) {
            return;
        }

        List<PvpPlayerInfo> list = pvpPlayerInfoServiceImpl.listCache(matchId);
        // 退出死亡的玩家
        List<PvpPlayerInfo> deadNeedExit =
                list.stream().filter(item -> item.getIsDead() == 1 && item.getIsExit() == 0).collect(Collectors.toList());
        for (PvpPlayerInfo pvpPlayerInfo : deadNeedExit) {
            exitGame(pvpPlayerInfo.getPlayerId(), matchId, 1);
        }

        // 胜利则清除所有存活的玩家
        List<PvpPlayerInfo> winnerlList = pvpPlayerInfoServiceImpl.obtainWinnerlList(matchId);
        // 有联盟获取胜利
        boolean b = winnerlList != null && !winnerlList.isEmpty();

        if (b) {
            List<PvpPlayerInfo> needExit = list.stream()
                    .filter(item -> item.getIsDead() == 0 && item.getIsExit() == 0)
                    .collect(Collectors.toList());
            for (PvpPlayerInfo pvpPlayerInfo : needExit) {
                exitGame(pvpPlayerInfo.getPlayerId(), matchId, 1);
            }
            endGame(matchId);
        }
    }


    @Transactional
    public void tryWorldSettlement(Long matchId) {
        pvpPlayerInfoServiceImpl.statisticalRanking(matchId);
        PvpMatch pvpMatch = pvpMatchServiceImpl.getById(matchId);
        if (pvpMatch == null) {
            pvpMatchServiceImpl.exitMatchHeart(matchId);
            return;
        }
        if (pvpMatch.getStatus() == 2) {
            pvpMatchServiceImpl.exitMatchHeart(matchId);
            return;
        }

        long gameStartTime = pvpMatch.getStartTime().getTime();
        int endTime = Integer.parseInt(CoreConfigServiceImpl.getCache(8L).getValue3()) * 60 * 1000;
        long durationOfPlay = System.currentTimeMillis() - gameStartTime;

        // log.info("尝试世界结算,比赛:{}游玩时长:{}分钟", matchId, durationOfPlay / 1000 / 60);


        if (durationOfPlay >= endTime) {
            List<PvpPlayerInfo> needExit = pvpPlayerInfoServiceImpl.listCache(matchId).stream()
                    .filter(item -> item.getIsExit() == 0)
                    .collect(Collectors.toList());
            for (PvpPlayerInfo pvpPlayerInfo : needExit) {
                exitGame(pvpPlayerInfo.getPlayerId(), matchId, 1);
            }
            endGame(matchId);
            return;
        }

        // 查看是否统治结束
        List<PvpPlayerInfo> collect = pvpPlayerInfoServiceImpl.listCache(matchId).stream()
                .filter(item -> item.getIsRuler() == 1)
                .collect(Collectors.toList());
        if (!collect.isEmpty()) {
            for (PvpPlayerInfo pvpPlayerInfo : collect) {
                exitGame(pvpPlayerInfo.getPlayerId(), matchId, 1);
                endGame(matchId);
                return;
            }
        }
    }


    @Transactional
    public void tryEnd(Long matchId) {
        PvpMatch byId = pvpMatchServiceImpl.getById(matchId);
        if (byId == null) {
            return;
        }

        if (byId.getStatus() != 1) {
            return;
        }

        if (byId.getType() == 2) {
            tryEndRobotMatch(matchId, byId);
        } else if (byId.getType() == 1) {
            tryWorldSettlement(matchId);
        }
        // 尝试结束游戏
        CoreConfig coreConfig = CoreConfigServiceImpl.getCache(8L);

        int endNeedMinutes = Integer.parseInt(coreConfig.getValue2());
        Date startTime = byId.getStartTime();

        DateTime dateTime = DateUtil.offsetMinute(startTime, endNeedMinutes);// 结束时间
        boolean before = dateTime.isBefore(new Date());

        if (before) {
            List<PvpPlayerInfo> pvpPlayerInfos = pvpPlayerInfoServiceImpl.listCache(matchId);
            if (pvpPlayerInfos.isEmpty()) { // 异常情况
                endGame(matchId);
            }
            List<PvpPlayerInfo> needExit = pvpPlayerInfos.stream()
                    .filter(item -> item.getIsExit() == 0)
                    .collect(Collectors.toList());
            PvpPlayerInfo winnerInfo = needExit.stream()
                    .max(Comparator.comparing(item -> item.getCurrentCity().size()))
                    .orElse(null);
            Long winnerId = winnerInfo == null ? 0 : winnerInfo.getPlayerId();
            for (PvpPlayerInfo pvpPlayerInfo : needExit) {
                PvpMatchEnd pvpMatchEnd = exitGame(pvpPlayerInfo.getPlayerId(), matchId, 1);
                if (winnerId.equals(pvpMatchEnd.getPlayerId())) {
                    Set<Long> alliesUidList = pvpPlayerInfo.getAlliesUidList();
                    for (Long rulerUid : alliesUidList) {
                        PvpMatchEnd select = select(matchId, rulerUid);
                        select.setIsRuler(1);
                        select.setEndType(3);
                        updateById(select);
                    }
                }
            }
        }
    }

    @Transactional
    public void tryEndRobotMatch(Long matchId, PvpMatch byId) {
        Set<Long> playerIds = byId.getPlayerIds();
        long maxPlayerId = 0L;
        if (playerIds != null && !playerIds.isEmpty()) {
            maxPlayerId = playerIds.stream().max(Long::compare).orElse(0L);
        }
        if (maxPlayerId < 1000) {
            endGame(matchId);
        }
    }

    /**
     * 结束游戏 不结算排名
     *
     * @param matchId 对局id
     */
    @Transactional
    public void endGame(Long matchId) {
        PvpMatch pvpMatch = pvpMatchServiceImpl.getById(matchId);
        List<PlayerStatus> list = playerMatchServiceImpl.list(new LambdaQueryWrapper<PlayerStatus>()
                .eq(PlayerStatus::getCurrentMatchId, matchId)
                .ne(PlayerStatus::getCurrentMatchId, 0)
        );

        if (list != null) {
            for (PlayerStatus playerMatch : list) {
                if (Objects.equals(pvpMatch.getId(), playerMatch.getCurrentMatchId())) {
                    playerMatch.setCurrentMatchId(0L);
                    playerMatchServiceImpl.updateById(playerMatch);
                }
            }
        }

        pvpMatch.setEndTime(new Date());
        pvpMatch.setStatus(2);
        pvpMatchServiceImpl.updateById(pvpMatch);

        pvpMatchServiceImpl.exitMatchHeart(matchId);
        pvpRoomServiceImpl.clearRoomByMatchId(matchId);

        if (pvpMatch.getType() == 2) {
            com.logic.modular.game.robot.po.RobotInfo.remove(matchId);
        }
    }

}
